Grundfälle der ebenen Vektoralgebra
Oktober 2020
Keywords: Webkinematik, Webentwicklung, Getriebekinematik, Mechanismentechnik, Bewegungsübertragung, Kraftübertragung, Vektoralgebra, g2, mec2
6.1 Grundfall I
6.1.1 Aufgabenstellung
Analysieren Sie den dargestellten Mechanismus und stellen Sie diesen anschließend interaktiv mit der g2-Bibliothek im Browser dar.
Geg.:
6.1.2 Kinematisches Modell
Modell 1: Kinematisches Modell
6.1.3 Lösung
Zur interaktiven Darstellung im Canvas-Element werden die Koordinaten der Gliedpunkt
Wir beginnen mit dem Aufstellen der Maschengleichung und identifizieren bzw. unterstreichen die unbekannten Größen. Anschließend wird die Gleichung derart umgeformt, sodass alle bekannten Variablen sich auf der rechten Seite befinden.
mit
Da es einen unbekannten Vektor mit zugehörigem unbekanntem Skalar gibt, identifizieren wir Grundfall I.
Grundfall I
Lösung
Die Länge
Nun kann die allgemeine Lösung des 1. Grundfalles zur Bestimmung des vorliegenden Mechanismus verwerdet werden. Für eine strukturierte Vorgehensweise eignet sich das Anlegen einer Tabelle.
| Grundfall I | Mechanismus |
|---|---|
Daraus resultiert
und
Die Umsetzung in HTML und JavaScript erfolgt entsprechend der Kapitel Animation und interaktive Elemente.
Als erstes wird ein Canvas-Element der Größe 500x400px, sowie ein Range-Input mit einem Bereich entsprechend der Vorgabe von mec-Objekt erstellt, das mittels number- & getter-Properties alle notwendigen Berechnungen vornimmt.
Nachdem die zu Beginn erarbeiteten mathematischen Erkenntnisse in Code überführt wurden, sollte das mec-Objekt folgendermaßen aussehen:
mec = {
h: 150,
l: 280,
get g() { return {x:-s, y:h}; },
get b() { return Math.sqrt(this.h*this.h + s*s); },
get psi() { return Math.atan2(this.h/this.b, -s/this.b); },
get epsi() { return {x:Math.cos(this.psi), y:Math.sin(this.psi)}; },
// Gelenkpunkte
get A() { return {x:+s, y:0}; },
get B() { return { x:0, y:this.h }; },
get C() { return { x:this.A.x + this.l*this.epsi.x, y:this.A.y + this.l*this.epsi.y }; }
}
Den Mechanismus und die zugegebenermaßen bei diesem Beispiel kaum vorhandene statische Umgebung, teilen wir wie gehabt in ein statisches (world)
// baut und initialisiert die statische Umgebung
world = g2().clr()
.view({cartesian:true,x:250,y:100}) // Nullpunkt verschoben
.use({grp:g})
.nodfix({...mec.B}),
und dynamisches (g) g2-Objekt auf, das wir in der postion()-Funktion füllen.
const g = g2();
//...
function position() {
g.del()
.bar({x1:mec.A.x, y1:mec.A.y, x2:mec.C.x, y2:mec.C.y})
.slider({...mec.B, w:mec.psi, fs:"@nodfill"})
.nodflt({...mec.A})
.nod({...mec.C})
}
Die Aktualisierung der Laufvariable, die Implementierung des dirty-flags, die Erstellung der render()-Funktion sowie des restlichen Quellcodes verhalten sich vollständig analog zu den Beispielen aus den vorherigen Kapiteln.
Der fertige Quelltext sollte folgendermaßen aussehen
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Schubschleife</title>
</head>
<body>
<h2>Schubschleife - Grundfall 1</h2>
<canvas id="c" width="500" height="400" style="border-width:1px;border-style:solid"></canvas>
<br>
<label for="sslider">s:
<input type="range" id="sslider" style="width:450px;vertical-align:middle;padding:0" min="-200" max="200" value="0">
<output id="sout" for="sslider">0</output>mm
</label>
<script src="https://gitcdn.xyz/repo/goessner/g2/master/src/g2.js"></script>
<script>
const cnv = document.getElementById('c'),
ctx = cnv.getContext('2d'),
sslider = document.getElementById('sslider'),
sout = document.getElementById('sout'),
mec = {
h: 150,
l: 280,
get g() { return {x:-s, y:h}; },
get b() { return Math.sqrt(this.h*this.h + s*s); },
get psi() { return Math.atan2(this.h/this.b, -s/this.b); },
get epsi() { return {x:Math.cos(this.psi), y:Math.sin(this.psi)}; },
// Gelenkpunkte
get A() { return { x:s, y:0}; },
get B() { return { x:0, y:this.h }; },
get C() { return { x:this.A.x + this.l*this.epsi.x, y:this.A.y + this.l*this.epsi.y }; }
},
g = g2(),
// baut und initialisiert statische Umgebung
world = g2().clr()
.view({cartesian:true,x:250,y:100}) // Nullpunkt verschoben
.use({grp:g})
.nodfix({...mec.B});
let s = 0, // Laufvariable
dirty = true; // wenn true gibt es was zu aktualisieren
function position() {
g.del()
.bar({x1:mec.A.x,y1:mec.A.y,x2:mec.C.x,y2:mec.C.y})
.slider({...mec.B, w:mec.psi})
.nodflt({...mec.A})
.nod({...mec.C})
}
function render() {
if (dirty) {
position(); // aktualisiere Position
world.exe(ctx); // rendert world in den Context
dirty = false;
}
requestAnimationFrame(render); // asynchroner callback von render(), keine Rekursion!
}
function sets() {
if (sslider.value != sout.value) {
s = +sslider.value;
sout.innerHTML = sslider.value;
dirty = true;
}
}
/*
* Initialisierung
*/
// Eventlistener hinzufuegen
sslider.addEventListener("input",sets);
// Animation starten
render();
</script>
</body>
</html>